
# coding:utf-8

import random
from lib import flux, al, pymunk
from lib.fluxext import ViewGroup, singleton
from utils.suger import *
from utils import dir2vec, limit
from utils.unit_attr import UnitAttr
from utils.unit_skill import UnitSkill


@singleton
class UnitManager(object):
    """这个东西唯一的存在意义就是保留引用"""
    units = {}
    nameless = []

    def add(self, unit, name=None):
        if name:
            self.units[name] = unit
        else:
            self.nameless.append(unit)

    def remove(self, unit):
        if unit in self.nameless:
            self.nameless.remove(unit)
            del unit
        else:
            for k,v in self.units.items():
                if v == unit:
                    del self.units[k]
                    break


class Unit(ViewGroup):
    """单位，拥有生命值，可以攻击，可以释放法术。"""
    def __init__(self, spd, force, size, last_dir=None, attr_type=UnitAttr):
        self.at_atk_cd = False

        if not last_dir:
            self.last_dir = random.choice([al.KEY_LEFT, al.KEY_RIGHT, al.KEY_UP, al.KEY_DOWN]) #默认面朝方向
        else:
            self.last_dir = last_dir
        self.dir_stack = []
        anchor = flux.View()
        anchor.SetAnchor(Game().map.map_top_left)

        self.anchor = anchor
        self.attr = attr_type(self)
        self.skill = UnitSkill(self)

        self.aim = None #当前没有锁定目标
        self.size = size
        self.attr.spd = spd # 基础移动速度
        self.attr.force = force # 加速度

        #self.bullet_type 若攻击为子弹类型，需要做这个设置

    def GetPos(self):
        return self.anchor.GetPos()

    def SetPos(self, x, y):
        """设置位置"""
        self.anchor.SetPos(x, y)

    def Anim(self, anim=None):
        return self.anchor.Anim(anim)

    def SetMapPos(self, x, y):
        self.anchor.SetPos(x* config.TILESIZE, y* config.TILESIZE)

    def GetMapPos(self):
        p = self.anchor.GetPos()
        return [p.x/ config.TILESIZE, p.y/ config.TILESIZE] #, p

    def GetAnchor(self):
        """获取锚点"""
        return self.anchor

    def SetAngle(self, angle):
        """获取角度"""
        self.anchor.SetAngle(angle)

    def SetSpeed(self, spd):
        self.spd = spd

    def Move(self, key):
        self.last_dir = key
        self.body.reset_forces()
        self.body.velocity = 0,0
        self.body.apply_force(dir2vec(self.last_dir, self.attr.force))
        self.dir_stack.append(key)

    def ResetSpeed(self):
        self.body.reset_forces()
        self.body.velocity = 0,0
        self.body.apply_force(dir2vec(self.last_dir, self.attr.force))

    def GetDir(self):
        return self.last_dir

    def Dead(self):
        smokesignal.emit('unit_dead', self)
        Game().unit.remove(self)

    def Attack(self):
        if not self.at_atk_cd:
            self.at_atk_cd = True
            _dir = self.GetDir()
            if _dir:
                bullet = self.bullet_type()
                x,y = self.GetMapPos()
                bullet.SetMapPos(x, y)
                bullet.Shoot(_dir)
                bullet.AddToScreen(Game().scr, 1)

            def OnFire():
                self.at_atk_cd = False

            t = flux.Timeout(self.attr.atk_interval)
            t.OnFire = OnFire
            t.Start()
            self.t = t
